package com.cy.springboot04notice.service.aspect;

import com.cy.springboot04notice.common.annotation.RequiredLog;
import com.cy.springboot04notice.pojo.SysLog;
import com.cy.springboot04notice.service.SysLogService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

@Component
@Aspect
@Order(1)//数字越小越优先
@Slf4j
public class SysLogAspect {

    @Pointcut("@annotation(com.cy.springboot04notice.common.annotation.RequiredLog)")
    public void doLog(){

    }

    @Around("doLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long t1= System.currentTimeMillis();
        log.info("before {}",t1);
        try {
            Object result = joinPoint.proceed();//调用切入点方法
            long t2=System.currentTimeMillis();
            log.info("after {}",t2);
            //记录详细的正常行为日志
            doLogInfo(joinPoint,(t2-t1),null);
            return result;//此返回值会交给代理对象，代理对象传给调用方法
        }catch(Throwable e){
            e.printStackTrace();
            Long t3=System.currentTimeMillis();
            log.error("exception {}",t3);
            //记录详细的异常行为日志
            doLogInfo(joinPoint,(t3-t1),e);
            throw e;
        }
    }

    @Autowired
    private SysLogService sysLogService;

    private void doLogInfo(ProceedingJoinPoint joinPoint, long time,Throwable e) throws Exception {
        //1.1获取登录用户名 (还没做登录时，先给假数据)
        String username="tony";
        //1.2获取ip(不会获取ip地址时先给假数据)
        String ip="202.106.29.20";
        Class<?> targetCls=joinPoint.getTarget().getClass();

        Signature signature=joinPoint.getSignature();
        MethodSignature ms= (MethodSignature)signature;

        Method targetMethod= targetCls.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
        RequiredLog requiredLog=targetMethod.getAnnotation(RequiredLog.class);
        String operation=requiredLog.operation();

        String targetClsMethod=targetCls.getName()+"."+targetMethod.getName();
        //1.5.1获取实际参数值
        Object[] args=joinPoint.getArgs();
        //1.5.2将参数值转换为json格式字符串(一种常用的数据格式)
        String jsonParamStr=new ObjectMapper().writeValueAsString(args);
        //2.封装日志
        SysLog userLog=new SysLog();
        userLog.setUsername(username);
        userLog.setIp(ip);
        userLog.setOperation(operation);
        userLog.setMethod(targetClsMethod);
        userLog.setParams(jsonParamStr);
        if(e!=null) {
            userLog.setStatus(0);//操作状态
            userLog.setError(e.getMessage());//错误信息
        }
        userLog.setTime(time);
        userLog.setCreatedTime(new Date());
        //3.记录日志
        // log.info("user.oper {}",userLog.toString());
        log.info("user.oper {}",new ObjectMapper().writeValueAsString(userLog));

        sysLogService.saveLog(userLog);
    }

}
